﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using EditAnyString.Models;
using System.Web;
using System.Web.Mvc;

namespace EditAnyString.MemoryStorage.Providers
{
	public class MemoryStorageProvider: EditAnyString.Providers.IEASStorageProvider
	{
		private readonly EditAnyString.Providers.IEASEditAuthorizationProvider _authProvider;
		// local copy
		private EditAnyString.Models.EditableStringDictionary _data;

		public MemoryStorageProvider( EditAnyString.Providers.IEASEditAuthorizationProvider authProvider )
		{
			_data = new EditAnyString.Models.EditableStringDictionary();
			_authProvider = authProvider;
		}

		#region IEASStorageProvider Members

		private bool canEdit
		{
			get { return _authProvider != null && _authProvider.CanEdit; }
		}

		public string Name
		{
			get { return "Memory storage provider"; }
		}

		public int StoreEASData( EditAnyString.Models.EditableStringDictionary source )
		{
			// just copy the data to local storage	
			_data.Clear();
			int added = 0;
			foreach( var kvp in source )
			{
				var newList = new List<EditableString>( kvp.Value.Count );
				foreach( var org in kvp.Value )
				{
					added++;
					newList.Add( new EditableString( org.Key, org.Context, org.Index, org.Value ) );
				}

				_data.Add( kvp.Key, newList );
			}
			return added;
		}

		public EditableString GetString( string context, string t, int? idx )
		{
			// first get the context
			IList<EditableString> strings;
			if( _data.TryGetValue( context, out strings ) )
			{
				int keyToFind = EditableString.GetKey( context, t, idx );
				// we have this context, so search for our string by key
				var found = strings.FirstOrDefault( x => x.Key == keyToFind );
				if( found != null )
					return found;
			}
			// if not found then return null
			return null;
		}

		public IList<EditableString> Search( int? searchKey, string searchContext, string searchValue, int pageIndex, int pageSize, out int total )
		{
			IEnumerable<EditableString> searchList = null;
			total = 0;

			// first check if we filter by context
			if( !string.IsNullOrWhiteSpace( searchContext ) )
			{
				var foundKVP = _data.Where( x => x.Key.IndexOf( searchContext, StringComparison.OrdinalIgnoreCase ) > -1 );
				if( !foundKVP.Any() )
					return new List<EditableString>();
				searchList = foundKVP.SelectMany( x => x.Value );
			}
			// if we don't have list yet, then get all for now
			if( searchList == null )
				searchList = _data.SelectMany( x => x.Value );
			// filter by key?
			if( searchKey != null )
				searchList = searchList.Where( x => x.Key == searchKey );
			// filter by value?
			if( !string.IsNullOrWhiteSpace( searchValue ) )
				searchList = searchList.Where( x => x.Value.IndexOf( searchValue, StringComparison.OrdinalIgnoreCase ) > -1 );

			total = searchList.Count();

			return searchList.Skip( pageIndex * pageSize ).Take( pageSize ).ToList();
		}

		public EditableString GetByKey( int key )
		{
			return _data.SelectMany( x => x.Value ).FirstOrDefault( x => x.Key == key );
		}

		public bool Update( int key, string value )
		{
			if( !canEdit )
				return false;

			var found = GetByKey( key );
			if( found == null )
				return false;
			found.Value = value;
			return true;
		}

		#endregion
	}
}
